package org.jchains.receiver;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;


import org.jchains.CORBA.PermissionTransferPackage.EnvironmentEntry;


public class PolicyFile {

	static final Logger log = Logger.getLogger("JChains");

	// 2 staged Hashtable with Perm-Leaf-Vectors as Leaves

	// -Level 0: Hashtable (key: permission codebase);
	// -Level 1: Hashtable (key: permission name);
	// -Level 2: Vector (elements: Perm objects);

	private String m_filename;

	Hashtable<String, Hashtable<String, Hashtable<String, Perm>>> ht_codebase = new Hashtable<String, Hashtable<String, Hashtable<String, Perm>>>();
	Hashtable<String, Boolean> permhandledcache = new Hashtable<String, Boolean>();
	EnvironmentEntry[] m_ee = new EnvironmentEntry[]{};

	public PolicyFile(String fn, EnvironmentEntry[] ee) {
		m_filename = fn;
		m_ee = ee;
	}
	
	

	public boolean add(Perm p) {

		String z = p.getMD5();

		if (permhandledcache.containsKey(z)) {
			return false;
		}

		permhandledcache.put(z, Boolean.TRUE);

		Hashtable<String, Hashtable<String, Perm>> ht_perm = ht_codebase
				.get(p.codebase);

		// name.replaceAll("\\","/");
		// log.info(p.pname + "/" + p.codebase);
		if (ht_perm == null) {
			ht_perm = new Hashtable<String, Hashtable<String, Perm>>();
			ht_codebase.put(p.codebase, ht_perm);
		}

		Hashtable<String, Perm> ve_vect = (Hashtable<String, Perm>) ht_perm
				.get(p.pname);
		if (ve_vect == null) {
			ve_vect = new Hashtable<String, Perm>();
			ht_perm.put(p.pname, ve_vect);
		}

		// Perm p = new Perm(codebase,pname, name, action);

		ve_vect.put(p.getMD5(), p);
		return true;
	}

	// void add(long time, String pname, String codebase, String name, String
	// action) {
	// add(new Perm(time,codebase,pname,name,action));
	// };

	static final String linesep = System.getProperty("line.separator");

	synchronized void toXML() {
		try {
			XMLEncoder xe = new XMLEncoder(new FileOutputStream(m_filename
					+ "xml"));
			xe.writeObject(this);
			xe.close();
		} catch (IOException ie) {
			ie.printStackTrace();
		}
	}

	public PolicyFile(String filename) throws IOException {
		XMLDecoder xd = new XMLDecoder(new FileInputStream(filename));
		PolicyFile f = (PolicyFile) xd.readObject();
		this.ht_codebase = f.ht_codebase;
		this.m_filename = f.m_filename;
		this.m_ee = f.m_ee;

		xd.close();
	}

	void save() {
		try {
			log.info("saving");
			// toXML();
			FileOutputStream fos = new FileOutputStream(m_filename);
			log.info("saving0");
			PrintWriter pw = new PrintWriter(fos, true);
			// String sb = getContent();
			log.info("saving2");
			pw.print(getContent(true));
			log.info("saving3");
			pw.close();
			log.info("saving4");
			fos.close();
		} catch (IOException e) {
			// log.warning(e.getMessage());
			log.warning("Unable to save!" + e);

		} catch (ClassCastException e) {
			log.warning("Unable to save!" + e);
			e.printStackTrace();
			// log.log(Level.WARNING, "class cast", e);
			// Throwable t = new Throwable();
		} catch (Exception e) {
			log.warning("Some exception occured :" + e.toString());
			log.warning(e.getMessage());
			log.log(Level.WARNING, "", e);
		}

	}

	public String getContent(boolean t) {
		StringBuffer sb = new StringBuffer(10000);
		log.info("before");
		// log.info(ht_codebase.toString());
		for (Enumeration e = ht_codebase.keys(); e.hasMoreElements();) {

			String codebase = (String) e.nextElement();
			log.info(codebase);
			sb.append("grant ");

			if (codebase.length() > 0) {
				sb.append(" Codebase ").append('"').append(codebase)
						.append('"');
			}
			sb.append(' ').append('{').append(linesep);
			Hashtable ht_perm = (Hashtable) ht_codebase.get(codebase);
			for (Enumeration f = ht_perm.keys(); f.hasMoreElements();) {
				String thePerm = (String) f.nextElement();
				Hashtable thePerms = (Hashtable) ht_perm.get(thePerm);
				for (Enumeration g = thePerms.elements(); g.hasMoreElements();) {
					Perm p = (Perm) g.nextElement();
					sb.append(p.getPermissionLine(true));
				}

			}
			sb.append("};").append(linesep);
		}
		return sb.toString();
	}
}
